<?php

namespace Xp\Feedback;

use InvalidArgumentException;
use PDO;
use Exception;
use PDOException;
use RuntimeException;

class Feedback
{
    private static ?Feedback $instance = null;
    private PDO $pdo;

    private function __construct(ConfigLoader $configLoader)
    {
        try {
            $dsn = sprintf(
                '%s:host=%s;port=%s;dbname=%s;charset=%s',
                $configLoader->get('driver'),
                $configLoader->get('host'),
                $configLoader->get('port', '3306'),
                $configLoader->get('database'),
                $configLoader->get('charset')
            );

            $this->pdo = new PDO(
                $dsn,
                $configLoader->get('username'),
                $configLoader->get('password'),
                [
                    PDO::ATTR_ERRMODE => PDO::ERRMODE_EXCEPTION,
                    PDO::ATTR_DEFAULT_FETCH_MODE => PDO::FETCH_ASSOC,
                    PDO::ATTR_EMULATE_PREPARES => false,
                ]
            );
        } catch (Exception $e) {
            throw new Exception("Database connection failed: " . $e->getMessage());
        }
    }

    public static function getInstance(ConfigLoader $configLoader): Feedback
    {
        if (self::$instance === null) {
            self::$instance = new Feedback($configLoader);
        }
        return self::$instance;
    }

    // 私有化克隆方法以防止克隆
    private function __clone() {}

    /**
     * 初始化反馈表
     */
    public function initializeTable()
    {
        $sql = file_get_contents(__DIR__ . '/../sql/init_feedback_db.sql');
        $this->pdo->exec($sql);
        echo "Feedback table initialized successfully.\n";
    }

    /**
     * 添加新反馈
     * @param int $uid
     * @param string|null $name
     * @param string $content
     * @param string|null $email
     * @return int
     */
    public function addFeedback(int $uid,?string $name,string $content,?string $email ): int
    {
        // 输入验证
        if (empty($uid) || empty($content)) {
            throw new InvalidArgumentException("UID and content are required fields.");
        }

        try {
            // 准备 SQL 语句
            $stmt = $this->pdo->prepare("
            INSERT INTO feedback (uid, name, email, content)
            VALUES (:uid, :name, :email, :content)
        ");

            // 执行 SQL 语句
            $stmt->execute([
                ':uid' => $uid,
                ':name' => $name ?? '',
                ':email' => $email,
                ':content' => $content
            ]);

            // 返回插入的 ID
            return (int)$this->pdo->lastInsertId();
        } catch (PDOException $e) {
            // 记录异常日志
            error_log("Database error: " . $e->getMessage());

            // 抛出异常
            throw new RuntimeException("Failed to insert feedback into the database.", 0, $e);
        }
    }

    /**
     * 获取所有反馈
     * @return array
     */
    public function getAllFeedbacks(): array
    {
        $stmt = $this->pdo->query('SELECT * FROM feedback ORDER BY created_at DESC');
        return $stmt->fetchAll(PDO::FETCH_ASSOC);
    }

}